home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / util / pack / xpk_Source.lha / xpk_Source / xpkmaster / xpkmaster.c < prev    next >
C/C++ Source or Header  |  1998-11-18  |  19KB  |  686 lines

  1. #ifndef XPKMASTER_XPKMASTER_C
  2. #define XPKMASTER_XPKMASTER_C
  3.  
  4. /* Routinesheader
  5.  
  6.     Name:        xpkmaster.c
  7.     Main:        xpkmaster
  8.     Versionstring:    $VER: xpkmaster.c 1.15 (13.09.1998)
  9.     Author:        SDI
  10.     Distribution:    Freeware
  11.     Description:    the main xpk functions
  12.  
  13.  1.0   09.10.96 : first real version
  14.  1.1   27.12.96 : removed 1.3 specific functions
  15.  1.2   10.01.97 : corrected XpkPack's abort
  16.  1.3   11.01.97 : corrected mem bug (reported by Laurent Kempe)
  17.  1.4   30.01.97 : hopefully fixed mem bug finally
  18.  1.5   31.01.97 : bug still occured
  19.  1.6   01.03.97 : added NoPack stuff to XpkWrite and XpkPack
  20.  1.7   24.03.97 : fixed XpkPack
  21.  1.8   25.03.97 : added AutoPasswd
  22.  1.9   28.03.97 : moved autopassword into xpkopen
  23.  1.10  01.04.97 : fixed NoPack error
  24.  1.11  19.12.97 : added xfdmaster support, made MBUG defines
  25.  1.12  09.01.98 : better passkey handling
  26.  1.13  21.02.98 : uses new style register definition
  27.  1.14  26.08.98 : lonely XpkWrite fixes
  28.  1.15  13.09.98 : added seek support, removed PP stuff
  29. */
  30.  
  31. /**************************************************/
  32. #ifdef __MAXON__                /**/
  33.   #define MBUGDEF    ULONG maxon_bug;    /**/
  34.   #define MBUG        maxon_bug = (ULONG)    /**/
  35. #else                        /**/
  36.   #define MBUG                      /**/
  37.   #define MBUGDEF                /**/
  38. #endif                        /**/
  39. /**************************************************/
  40.  
  41. #include <proto/exec.h>
  42. #include <proto/intuition.h>
  43. #include <proto/dos.h>
  44. #include <proto/utility.h>
  45. #include <proto/xpkmaster.h>
  46. #include <proto/xfdmaster.h>
  47. #include <proto/xpksub.h>
  48. #include <exec/types.h>
  49. #include <exec/memory.h>
  50. #include <exec/tasks.h>
  51. #include <dos/dos.h>
  52. #include "xpkmaster.h"
  53. #include "texts.h"
  54.  
  55. #ifdef SUPPORT_A4
  56.   LONG XpkOpenA4NAME(struct XpkFib **xfh, struct TagItem *tags, ULONG a4);
  57.   #ifdef __SASC
  58.     #pragma libcall XpkBase XpkOpenA4NAME 036 C9803
  59.   #else
  60.     #pragma amicall(XpkBase,0x36,XpkOpenA4NAME(a0,a1,a4))
  61.   #endif
  62. #else
  63.   #define XpkOpenA4NAME XpkOpen
  64. #endif
  65.  
  66. /**************************************************************************
  67.  *
  68.  *   XpkPack() - pack a file
  69.  *
  70.  */
  71.  
  72. ASM(LONG) LIBXpkPack(REG(a0, struct TagItem *tags) A4PROTO)
  73. {
  74.   struct XpkBuffer *xbuf = 0;
  75.   STRPTR buf;
  76.   LONG totlen, res, chunklen;
  77.  
  78. #ifdef DEBUG
  79.   DebugRunTime("XpkPack");
  80. #endif
  81.  
  82.   if(!FindTagItem(XPK_PackMethod, tags))
  83.     return XPKERR_BADPARAMS;
  84.  
  85.   if((res = XpkOpenA4NAME((struct XpkFib **) &xbuf, tags A4SUPP)))
  86.     return res;
  87.  
  88.   if((totlen = xbuf->xb_InLen) == 0xFFFFFFFF)
  89.   {
  90.     xbuf->xb_Result = XPKERR_BADPARAMS;
  91.     return XpkClose((struct XpkFib *) xbuf);
  92.   }
  93.  
  94.   CurrentTime(&xbuf->xb_Secs, &xbuf->xb_Mics); /* Start the clock */
  95.  
  96.   xbuf->xb_Prog.xp_Type = XPKPROG_START;
  97.   xbuf->xb_Prog.xp_ULen = totlen;
  98.   if(callprogress(xbuf))
  99.     return XpkClose((struct XpkFib *) xbuf);
  100.  
  101.   while(totlen > 0)
  102.   {
  103.     chunklen = xbuf->xb_Fib.xf_NLen;
  104.  
  105.     if(!(buf = (STRPTR) hookread(xbuf, XIO_READ, NULL, chunklen)))
  106.       break;
  107.  
  108.     if(XpkWrite((struct XpkFib *) xbuf, buf, chunklen))
  109.       break;
  110.  
  111.     totlen -= chunklen;
  112.  
  113.     xbuf->xb_Prog.xp_Type = XPKPROG_MID;    /* Progress report     */
  114.     xbuf->xb_Prog.xp_UCur += chunklen;
  115.     xbuf->xb_Prog.xp_CCur = xbuf->xb_Fib.xf_CCur;
  116.     if(callprogress(xbuf))
  117.       return XpkClose((struct XpkFib *) xbuf);
  118.   }
  119.  
  120.   if(xbuf->xb_Prog.xp_Type)
  121.   {
  122.     xbuf->xb_Prog.xp_Type = XPKPROG_END;
  123.     xbuf->xb_Prog.xp_CCur += xbuf->xb_Headers.h_LocSize;
  124.     xbuf->xb_Prog.xp_Activity = xbuf->xb_Result ?
  125.       strings[TXT_ABORTED] : xbuf->xb_LastMsg;
  126.     callprogress(xbuf);     /* Call the hook one last time */
  127.   }
  128.  
  129.   return XpkClose((struct XpkFib *) xbuf);
  130. }
  131.  
  132. /*********************************************************************
  133.  *
  134.  * XpkUnpack - unpack a file
  135.  *
  136.  */
  137.  
  138. ASM(LONG) LIBXpkUnpack(REG(a0, struct TagItem *tags) A4PROTO)
  139. {
  140.   struct XpkBuffer *xbuf = NULL;
  141.   STRPTR pointer;
  142.   LONG len, res;
  143.  
  144. #ifdef DEBUG
  145.   DebugRunTime("XpkUnpack");
  146. #endif
  147.  
  148.   if((res = XpkOpenA4NAME((struct XpkFib **) &xbuf, tags A4SUPP)))
  149.     return res;
  150.  
  151.   if(xbuf->xb_Flags & XMF_PACKING)
  152.   {
  153.     xbuf->xb_Result = XPKERR_BADPARAMS;
  154.     goto Abort;
  155.   }
  156.  
  157.   CurrentTime(&xbuf->xb_Secs, &xbuf->xb_Mics); /* Start the clock */
  158.  
  159.   xbuf->xb_Prog.xp_Type = XPKPROG_START;    /* Initialize progress */
  160.   xbuf->xb_Prog.xp_ULen = xbuf->xb_Fib.xf_ULen;
  161.   if(callprogress(xbuf))
  162.     goto Abort;
  163.  
  164.   if(!hookwrite(xbuf, XIO_TOTSIZE, NULL, xbuf->xb_Fib.xf_ULen + XPK_MARGIN))
  165.   {
  166. #ifdef DEBUG
  167.     DebugError("XpkUnpack: XIO_TOTSIZE failed");
  168. #endif
  169.     goto Abort;
  170.   }
  171.  
  172.   if(!(pointer = (STRPTR) hookwrite(xbuf, XIO_GETBUF, 0, xbuf->xb_Fib.xf_NLen)))
  173.   {
  174. #ifdef DEBUG
  175.     DebugError("XpkUnpack: XIO_GETBUF failed (a)");
  176. #endif
  177.     goto Abort;
  178.   }
  179.  
  180. #ifdef DEBUG
  181.   if(xbuf->xb_Result)
  182.     DebugError("XpkUnpack: failure before unpackloop");
  183. #endif
  184.  
  185.   while((len = XpkRead((struct XpkFib *) xbuf, pointer, xbuf->xb_Fib.xf_NLen)) > 0)
  186.   {
  187.     if(!hookwrite(xbuf, XIO_WRITE, pointer, len))
  188.     {
  189. #ifdef DEBUG
  190.       DebugError("XpkUnpack: XIO_WRITE failed");
  191. #endif
  192.       goto Abort;
  193.     }
  194.  
  195.     xbuf->xb_Prog.xp_Type = XPKPROG_MID;    /* Progress report     */
  196.     xbuf->xb_Prog.xp_CCur = xbuf->xb_Fib.xf_CCur;
  197.     xbuf->xb_Prog.xp_UCur = xbuf->xb_Fib.xf_UCur;
  198.     if(callprogress(xbuf))
  199.       goto Abort;
  200.  
  201.     if(!(pointer = (STRPTR) hookwrite(xbuf, XIO_GETBUF, NULL, xbuf->xb_Fib.xf_NLen)))
  202.     {
  203. #ifdef DEBUG
  204.       DebugError("XpkUnpack: XIO_GETBUF failed (b)");
  205. #endif
  206.       goto Abort;
  207.     }
  208.   }
  209.  
  210.   xbuf->xb_Result = len;
  211. #ifdef DEBUG
  212.   if(xbuf->xb_Result)
  213.     DebugError("XpkUnpack: XpkRead failed with %ld", xbuf->xb_Result);
  214. #endif
  215.  
  216.   if(xbuf->xb_Prog.xp_Type)
  217.   {
  218.     xbuf->xb_Prog.xp_Type = XPKPROG_END;
  219.     xbuf->xb_Prog.xp_Activity = xbuf->xb_Result ? strings[TXT_ABORTED] : xbuf->xb_LastMsg;
  220.     callprogress (xbuf);    /* Call the hook one last time */
  221.   }
  222. Abort:
  223.   return XpkClose((struct XpkFib *) xbuf);
  224. }
  225.  
  226. /*********************************************************************
  227.  *
  228.  * XpkOpen - open a file for packing/unpacking
  229.  *
  230.  */
  231.  
  232. ASM(LONG) LIBXpkOpen(REG(a0, struct XpkBuffer **xbufp),
  233.     REG(a1, struct TagItem *tags) A4PROTO)
  234. {
  235. #if defined(DEBUG) && defined(SUPPORT_A4)
  236.   DebugRunTime("XpkOpen: A4 = %ld", a4);
  237. #elif defined(DEBUG)
  238.   DebugRunTime("XpkOpen");
  239. #endif
  240.   return xpkopen(xbufp, tags, 0 A4SUPP);
  241. }
  242.  
  243. /**************************************************************************
  244.  *
  245.  *   XpkExamine() - inspect a compressed file
  246.  *
  247.  */
  248.  
  249. ASM(LONG) LIBXpkExamine(REG(a0, struct XpkFib *fib),
  250.     REG(a1, struct TagItem *tags) A4PROTO)
  251. {
  252.   struct XpkBuffer *dummy;
  253.   LONG res;
  254.  
  255. #if defined(DEBUG) && defined(SUPPORT_A4)
  256.   DebugRunTime("XpkExamine: A4 = %ld", a4);
  257. #elif defined(DEBUG)
  258.   DebugRunTime("XpkExamine");
  259. #endif
  260.  
  261.   if((res = xpkopen(&dummy, tags, 1 A4SUPP)))
  262.     return res;
  263.  
  264.   CopyMem(dummy, fib, sizeof(struct XpkFib));
  265.   /* copies the entries of XpkFib
  266.      *fib = dummy->Fib works too, but calls it's own copy-function */
  267.  
  268.   return XpkClose((struct XpkFib *) dummy);
  269. }
  270.  
  271. /**************************************************************************
  272.  *
  273.  *   XpkRead() - read one chunk from a compressed file
  274.  *
  275.  */
  276.  
  277. ASM(LONG) LIBXpkRead(REG(a0, struct XpkBuffer *xbuf), REG(a1, STRPTR buf),
  278.     REG(d0, ULONG len))
  279. {
  280.   MBUGDEF
  281.  
  282. #ifdef DEBUG
  283.   DebugRunTime("XpkRead: buf %08lx, size %ld", buf, len);
  284. #endif
  285.  
  286.   if(!xbuf)
  287.     return XPKERR_NOFUNC;
  288.  
  289.   if(xbuf->xb_Flags & XMF_EOF)
  290.     return 0;
  291.  
  292.   switch(xbuf->xb_Format) 
  293.   {
  294.     /*********************** Unpack standard XPK *******************/
  295.   case XPKMODE_UPSTD:
  296.     {
  297.       struct XpkSubParams *xpar;
  298.       struct Library *XpkSubBase = xbuf->xb_SubBase;
  299.       XpkChunkHeader *lochdr = &(xbuf->xb_Headers.h_Loc);
  300.       LONG ulen, clen, rclen, lochdrsize = xbuf->xb_Headers.h_LocSize;
  301.       ULONG csum;
  302.  
  303.       if(lochdr->xch_Word.xchw_Type == XPKCHUNK_END)
  304.         return 0;
  305.  
  306.       if((MBUG hchecksum((STRPTR) lochdr, lochdrsize)))
  307.       {
  308. #ifdef DEBUG
  309.         DebugError("XpkRead: hchecksum(,%ld) failed", lochdrsize);
  310. #endif
  311.         return(xbuf->xb_Result = XPKERR_CHECKSUM);
  312.       }
  313.  
  314.       getUClen(xbuf, &ulen, &clen);
  315.       rclen = ROUNDLONG(clen);
  316.  
  317.       if(lochdr->xch_Word.xchw_Type == XPKCHUNK_RAW)
  318.       {
  319.         if(!(MBUG hookread(xbuf, XIO_READ, buf, rclen + lochdrsize)))
  320.       return xbuf->xb_Result;
  321.  
  322.         if(!(xbuf->xb_Flags & XMF_NOCRC))
  323.       if((csum=cchecksum((ULONG *) buf, rclen >>2)) != lochdr->xch_Word.xchw_CChk)
  324.       {
  325. #ifdef DEBUG
  326.         DebugError("XpkRead: cchecksum(,%ld) = %lx != %lx failed", rclen >> 2, csum, (ULONG) lochdr->xch_Word.xchw_CChk);
  327. #endif
  328.         return (xbuf->xb_Result = XPKERR_CHECKSUM);
  329.           }
  330.  
  331.         CopyMem(buf + rclen, lochdr, lochdrsize);
  332.       }
  333.       else if(lochdr->xch_Word.xchw_Type == XPKCHUNK_PACKED)
  334.       {
  335.         xpar = &xbuf->xb_PackParam;
  336.         if(!(xpar->xsp_InBuf = hookread(xbuf, XIO_READ, NULL, rclen + lochdrsize)))
  337.       return xbuf->xb_Result;
  338.  
  339.         if(!(xbuf->xb_Flags & XMF_NOCRC))
  340.       if((csum=cchecksum((ULONG *)xpar->xsp_InBuf, rclen >> 2)) != lochdr->xch_Word.xchw_CChk)
  341.       {
  342. #ifdef DEBUG
  343.         DebugError("XpkRead: cchecksum(,%ld) = %lx != %lx failed", rclen >>2 , csum, (ULONG) lochdr->xch_Word.xchw_CChk);
  344. #endif
  345.         return (xbuf->xb_Result = XPKERR_CHECKSUM);
  346.           }
  347.         xbuf->xb_Flags |= XMF_INITED;
  348.  
  349.         xpar->xsp_InLen = clen;
  350.         xpar->xsp_OutLen = ulen;
  351.         xpar->xsp_OutBuf = buf;
  352.         xpar->xsp_OutBufLen = ulen;
  353.         xpar->xsp_Number = 0;
  354.         xpar->xsp_Password = xbuf->xb_Password;
  355.         xpar->xsp_LibVersion = xbuf->xb_Headers.h_Glob.xsh_SubVrs;
  356.  
  357.         if((xbuf->xb_Result = XpksUnpackChunk(xpar)))
  358.       return xbuf->xb_Result;
  359.  
  360.         CopyMem((STRPTR) xpar->xsp_InBuf + rclen, lochdr, lochdrsize);
  361.       }
  362.       else
  363.         return (xbuf->xb_Result = XPKERR_CORRUPTPKD);
  364.  
  365.       if(updatefib(xbuf))
  366.         return xbuf->xb_Result;
  367.       return ulen;
  368.     }
  369.  
  370.   /**************************** xfdmaster file **************************/
  371.   case XPKMODE_UPXFD:
  372.     {
  373.       struct xfdMasterBase *xfdMasterBase = (struct xfdMasterBase *) xbuf->xb_SubBase;
  374.       struct xfdBufferInfo *xbi = xbuf->xb_xfd;
  375.  
  376.       xbi->xfdbi_Flags = XFDFF_USERTARGET;
  377.       xbi->xfdbi_UserTargetBuf = buf;
  378.       xbi->xfdbi_UserTargetBufLen = len;
  379.       if((xbuf->xb_Fib.xf_Flags & XPKFLAGS_KEY32) &&
  380.       (xbuf->xb_Flags & XMF_KEY32))
  381.         xbi->xfdbi_Special = &xbuf->xb_PassKey32;
  382.       else if((xbuf->xb_Fib.xf_Flags & XPKFLAGS_KEY16) &&
  383.       (xbuf->xb_Flags & XMF_KEY16))
  384.         xbi->xfdbi_Special = &xbuf->xb_PassKey16;
  385.       else if(xbuf->xb_Fib.xf_Flags & XPKFLAGS_PASSWORD)
  386.         xbi->xfdbi_Special = xbuf->xb_Password;
  387.  
  388.       if(!xfdDecrunchBuffer(xbi))
  389.       {
  390.         switch(xbi->xfdbi_Error)
  391.         {
  392.         case XFDERR_NOMEMORY: xbuf->xb_Result = XPKERR_NOMEM; break;
  393.         case XFDERR_WRONGPASSWORD: case XFDERR_WRONGKEY:
  394.           xbuf->xb_Result = XPKERR_WRONGPW; break;
  395.         case XFDERR_CORRUPTEDDATA: xbuf->xb_Result = XPKERR_CORRUPTPKD; break;
  396.         case XFDERR_BETTERCPU: xbuf->xb_Result = XPKERR_WRONGCPU; break;
  397.         default: xbuf->xb_Result = XPKERR_UNKNOWN; break;
  398.         }
  399.  
  400. #ifdef DEBUG
  401.   DebugRunTime("XpkRead: xfd failed with %ld", xbuf->xb_Result);
  402. #endif
  403.         return xbuf->xb_Result;
  404.       } /* xfdDecrunchBuffer */
  405.  
  406.       xbuf->xb_Fib.xf_CCur = xbuf->xb_InLen;
  407.       xbuf->xb_Fib.xf_UCur = xbuf->xb_Fib.xf_ULen;
  408.       xbuf->xb_Fib.xf_NLen = 0;
  409.       xbuf->xb_Flags |= XMF_EOF;
  410.  
  411. #ifdef DEBUG
  412.   DebugRunTime("XpkRead: xfd returns %ld", xbuf->xb_Fib.xf_ULen);
  413. #endif
  414.       return (LONG) xbuf->xb_Fib.xf_ULen;
  415.     }
  416.     /********************* Unpack unpacked file *******************/
  417.   case XPKMODE_UPUP:
  418.     {
  419.       ULONG leftlen = xbuf->xb_Fib.xf_ULen - xbuf->xb_Fib.xf_CCur;
  420.  
  421.       if(leftlen > len)
  422.     leftlen = len;
  423.       else
  424.         xbuf->xb_Flags |= XMF_EOF;
  425.  
  426.       if(!(MBUG hookread(xbuf, XIO_READ, buf, leftlen)))
  427.         return xbuf->xb_Result;
  428.  
  429.       xbuf->xb_Fib.xf_CCur += leftlen;
  430.       xbuf->xb_Fib.xf_UCur += leftlen;
  431.       xbuf->xb_Fib.xf_NLen = Min(xbuf->xb_InLen -
  432.         xbuf->xb_Fib.xf_UCur, DEFAULTCHUNKSIZE) + XPK_MARGIN;
  433.  
  434.       return (LONG) leftlen;
  435.     }
  436.   }
  437.  
  438.   return xbuf->xb_Result;
  439. }
  440.  
  441. /**************************************************************************
  442.  *
  443.  *   XpkWrite() - write a chunk to a compressed file
  444.  *
  445.  */
  446.  
  447. ASM(LONG) LIBXpkWrite(REG(a0, struct XpkBuffer *xbuf), REG(a1, STRPTR buf),
  448.     REG(d0, ULONG ulen))
  449. {
  450.   struct Library *XpkSubBase = xbuf->xb_SubBase;
  451.   struct XpkSubParams *xpar;
  452.   struct Headers *head = &xbuf->xb_Headers;
  453.   LONG clen, rclen, outbuflen;
  454.   UWORD end[2] = {0,0}; /* last ULONG of buffer, when not longword bounded */
  455.   UBYTE type;
  456.   STRPTR outbuf;
  457.   MBUGDEF
  458.  
  459. #ifdef DEBUG
  460.   DebugRunTime("XpkWrite: buf %08lx, size %ld", buf, ulen);
  461. #endif
  462.  
  463.   if(!xbuf->xb_FirstChunk)
  464.     xbuf->xb_FirstChunk = ulen;
  465.   if(ulen > xbuf->xb_FirstChunk)
  466.     return (xbuf->xb_Result = XPKERR_BADPARAMS);
  467.  
  468.   if(xbuf->xb_Flags & XMF_NOPACK) /* no packing */
  469.   {
  470.     hookwrite(xbuf, XIO_WRITE, buf, ulen);
  471.     xbuf->xb_Fib.xf_UCur += ulen;
  472.     xbuf->xb_Fib.xf_CCur += ulen;
  473.     xbuf->xb_Fib.xf_NLen = Min(xbuf->xb_InLen - xbuf->xb_Fib.xf_UCur,
  474.       (LONG) xbuf->xb_ChunkSize);
  475.     return xbuf->xb_Result;
  476.   }
  477.  
  478.   /******************* Write the GlobHdr ********************/
  479.   if(!(xbuf->xb_Flags & XMF_GLOBHDR))
  480.   {
  481.     if(!xbuf->xb_Password)
  482.       CopyMem(buf, head->h_Glob.xsh_Initial, Min(16, ulen));
  483.     xbuf->xb_Flags |= XMF_GLOBHDR;
  484.     if(!(MBUG hookwrite(xbuf, XIO_WRITE, &head->h_Glob,
  485.     sizeof(struct XpkStreamHeader))))
  486.       return xbuf->xb_Result;
  487.     xbuf->xb_Fib.xf_CCur += sizeof(struct XpkStreamHeader);
  488.   }
  489.  
  490.   /******************* Allocate the buffer *****************/
  491.   outbuflen = ROUNDLONG(ulen + (ulen>>5) + head->h_LocSize) + XPK_MARGIN;
  492.   if(!(outbuf = (STRPTR) hookwrite(xbuf, XIO_GETBUF, NULL, outbuflen)))
  493.     return xbuf->xb_Result;
  494.  
  495.   outbuf += head->h_LocSize;
  496.   /* compress to behind local header. This is needed by mem-out hook! */
  497.  
  498.   if(ulen < xbuf->xb_SubInfo->xi_MinPkInChunk)
  499.     goto copychunk;
  500.  
  501.   /******************* Pack the chunk **********************/
  502.   xpar = &xbuf->xb_PackParam;
  503.   xpar->xsp_InBuf = buf;
  504.   xpar->xsp_InLen = ulen;
  505.   xpar->xsp_OutBuf = outbuf;
  506.   xpar->xsp_OutBufLen = outbuflen - head->h_LocSize;
  507.   xpar->xsp_Number += 1;
  508.   xpar->xsp_Mode = xbuf->xb_PackingMode;
  509.   xpar->xsp_Password = xbuf->xb_Password;
  510.   xpar->xsp_LibVersion = xbuf->xb_SubInfo->xi_LibVersion;
  511.  
  512.   xbuf->xb_Result = XpksPackChunk(xpar);
  513.   xbuf->xb_Flags |= XMF_INITED;
  514.  
  515.   type = XPKCHUNK_PACKED;
  516.   clen = xpar->xsp_OutLen;
  517.  
  518.   if(xbuf->xb_Result == XPKERR_EXPANSION)
  519.   {
  520.     xbuf->xb_Result = 0;
  521. copychunk:
  522.     type = XPKCHUNK_RAW;
  523.     clen = ulen;
  524.     outbuf = buf;
  525.   }
  526.  
  527.   if(xbuf->xb_Result)
  528.     return xbuf->xb_Result;
  529.  
  530.   /******************* Write the chunk **********************/
  531.   head->h_Loc.xch_Word.xchw_Type = type;
  532.   if(head->h_Glob.xsh_Flags & XPKSTREAMF_LONGHEADERS)
  533.   {
  534.     head->h_Loc.xch_Long.xchl_ULen = ulen;
  535.     head->h_Loc.xch_Long.xchl_CLen = clen;
  536.   }
  537.   else
  538.   {
  539.     head->h_Loc.xch_Word.xchw_ULen = (WORD) ulen;
  540.     head->h_Loc.xch_Word.xchw_CLen = (WORD) clen;
  541.   }
  542.  
  543.   if((rclen = clen&3))
  544.   {
  545.     clen -= rclen;
  546.     CopyMem(outbuf+clen, &end, rclen); /* copy the remaining bytes (max 3) */
  547.   }
  548.  
  549.   head->h_Loc.xch_Word.xchw_CChk = cchecksum((ULONG *) outbuf, clen >> 2)
  550.     ^ end[0] ^ end[1];
  551.   /* add the rest bytes to the checksum */
  552.   
  553.   head->h_Loc.xch_Word.xchw_HChk = 0;
  554.   head->h_Loc.xch_Word.xchw_HChk = hchecksum((STRPTR) &head->h_Loc, head->h_LocSize);
  555.  
  556.   if(!(MBUG hookwrite(xbuf, XIO_WRITE, &head->h_Loc, head->h_LocSize)))
  557.     return xbuf->xb_Result;
  558.  
  559.   if(!(MBUG hookwrite(xbuf, XIO_WRITE, outbuf, clen)))
  560.     return xbuf->xb_Result;
  561.  
  562.   if(rclen)
  563.   {
  564.     if(!(MBUG hookwrite(xbuf, XIO_WRITE, &end, 4)))
  565.       return xbuf->xb_Result;
  566.     clen += 4;
  567.   }
  568.  
  569.   head->h_Glob.xsh_ULen += ulen;
  570.   
  571.   xbuf->xb_Fib.xf_UCur += ulen;
  572.   xbuf->xb_Fib.xf_CCur += head->h_LocSize + clen;
  573.   xbuf->xb_Fib.xf_NLen = Min(max(xbuf->xb_InLen, head->h_Glob.xsh_ULen) -
  574.     xbuf->xb_Fib.xf_UCur, (LONG) xbuf->xb_ChunkSize);
  575.  
  576.   return xbuf->xb_Result;
  577. }
  578.  
  579. /**************************************************************************
  580.  *
  581.  *   XpkClose() - finish (de)compressing an XPK file
  582.  *
  583.  */
  584.  
  585. ASM(LONG) LIBXpkClose(REG(a0, struct XpkBuffer *xbuf))
  586. {
  587.   struct Library *XpkSubBase = xbuf->xb_SubBase;
  588.  
  589.   if(!xbuf)
  590.     return 0;
  591.  
  592. #ifdef DEBUG
  593.   if(xbuf->xb_Result)
  594.     DebugError("XpkClose: failed (%ld) before XpkClose", xbuf->xb_Result);
  595. #endif
  596.  
  597.   if(xbuf->xb_Format == XPKMODE_PKSTD)
  598.   {
  599.     struct Headers *head = &xbuf->xb_Headers;
  600.     LONG outlen;
  601.  
  602.     if(!xbuf->xb_Result && !(xbuf->xb_Flags & XMF_GLOBHDR|XMF_NOPACK))
  603.     {
  604.       hookwrite(xbuf, XIO_WRITE, &head->h_Glob, sizeof(struct XpkStreamHeader));
  605. #ifdef DEBUG
  606.       if(xbuf->xb_Result) DebugError("XpkClose: failed to write globhdr");
  607. #endif
  608.       xbuf->xb_Fib.xf_CCur += sizeof(struct XpkStreamHeader);
  609.     }
  610.     if(!xbuf->xb_Result && !(xbuf->xb_Flags & XMF_NOPACK))
  611.     {
  612.       /******************* Write final chunk header *****************/
  613.       memset(&head->h_Loc, 0, head->h_LocSize);
  614.       head->h_Loc.xch_Word.xchw_Type = XPKCHUNK_END;
  615.       head->h_Loc.xch_Word.xchw_HChk = 0;
  616.       head->h_Loc.xch_Word.xchw_HChk =
  617.         hchecksum((STRPTR) &head->h_Loc, head->h_LocSize);
  618.  
  619.       hookwrite(xbuf, XIO_WRITE, &head->h_Loc, head->h_LocSize);
  620. #ifdef DEBUG
  621.       if(xbuf->xb_Result) DebugError("XpkClose: failed to write lochdr");
  622. #endif
  623.       xbuf->xb_Fib.xf_CCur += head->h_LocSize;
  624.       outlen = xbuf->xb_Fib.xf_CCur;
  625.  
  626.       /********************** Write global header *******************/
  627.       hookwrite(xbuf, XIO_SEEK, NULL, -outlen);
  628. #ifdef DEBUG
  629.       if(xbuf->xb_Result) DebugError("XpkClose: failed to reset output");
  630. #endif
  631.  
  632.       head->h_Glob.xsh_Pack = XPK_COOKIE;
  633.       head->h_Glob.xsh_CLen = outlen - 8;
  634.       head->h_Glob.xsh_HChk = 0;
  635.       head->h_Glob.xsh_HChk =
  636.         hchecksum((STRPTR) &head->h_Glob, sizeof(struct XpkStreamHeader));
  637.  
  638.       hookwrite(xbuf, XIO_WRITE, &head->h_Glob, sizeof(struct XpkStreamHeader));
  639. #ifdef DEBUG
  640.       if(xbuf->xb_Result) DebugError("XpkClose: failed updating globalhdr");
  641. #endif
  642.  
  643.       hookwrite(xbuf, XIO_SEEK, 0, outlen - sizeof(struct XpkStreamHeader));
  644. #ifdef DEBUG
  645.       if(xbuf->xb_Result) DebugError("XpkClose: failed to SEEK to end of output");
  646. #endif
  647.     }
  648.     xbuf->xb_Fib.xf_CLen = xbuf->xb_Fib.xf_CCur;
  649.     xbuf->xb_Fib.xf_ULen = xbuf->xb_Fib.xf_UCur;
  650.  
  651.     /*************************** Shut down *************************/
  652.     if(xbuf->xb_Flags & XMF_INITED)
  653.       XpksPackFree(&xbuf->xb_PackParam);
  654.   }
  655.   else if(xbuf->xb_Format == XPKMODE_UPSTD && xbuf->xb_Flags & XMF_INITED)
  656.     XpksUnpackFree(&xbuf->xb_PackParam);
  657.  
  658.   if(xbuf->xb_RHook)
  659.   {
  660.     hookread(xbuf, xbuf->xb_Result ? XIO_ABORT : XIO_FREE, NULL, 0);
  661. #ifdef DEBUG
  662.     if(xbuf->xb_Result) DebugError("XpkClose: failed read ABORT/FREE");
  663. #endif
  664.   }
  665.  
  666.   if(xbuf->xb_WHook)
  667.   {
  668.     hookwrite(xbuf, xbuf->xb_Result ? XIO_ABORT : XIO_FREE, NULL, 0);
  669. #ifdef DEBUG
  670.     if(xbuf->xb_Result) DebugError("XpkClose: failed write ABORT/FREE");
  671. #endif
  672.   }
  673.  
  674.   parsegettags(xbuf);        /* Send information to the user */
  675.  
  676. #ifdef DEBUG
  677.     DebugRunTime("XpkClose: InLen %ld, CLen %ld, ULen %ld, ID %.4s", xbuf->xb_InLen,
  678.     xbuf->xb_Fib.xf_CLen, xbuf->xb_Fib.xf_ULen, &xbuf->xb_Fib.xf_ID);
  679. #endif
  680.  
  681.   return freebufs(xbuf);
  682. }
  683.  
  684. #endif /* XPKMASTER_XPKMASTER_C */
  685.  
  686.